<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>GLSL语法 | Lo动乾坤</title><meta name="keywords" content="GLSL"><meta name="author" content="韩少邱,657220266@qq.com"><meta name="copyright" content="韩少邱"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="description" content="GLSL 中文手册  基本类型:    类型 说明     void 空类型,即不返回任何值   bool 布尔类型 true,false   int 带符号的整数 signed integer   float 带符号的浮点数 floating scalar   vec2, vec3, vec4 n维浮点数向量 n-component floating point vector   bvec2,">
<meta property="og:type" content="article">
<meta property="og:title" content="GLSL语法">
<meta property="og:url" content="https://hanlovesong.gitee.io/2021/02/25/GLSL%E8%AF%AD%E6%B3%95/index.html">
<meta property="og:site_name" content="Lo动乾坤">
<meta property="og:description" content="GLSL 中文手册  基本类型:    类型 说明     void 空类型,即不返回任何值   bool 布尔类型 true,false   int 带符号的整数 signed integer   float 带符号的浮点数 floating scalar   vec2, vec3, vec4 n维浮点数向量 n-component floating point vector   bvec2,">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/img/default.jpg">
<meta property="article:published_time" content="2021-02-25T12:02:34.000Z">
<meta property="article:modified_time" content="2021-02-25T13:09:01.190Z">
<meta property="article:author" content="韩少邱">
<meta property="article:tag" content="GLSL">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/img/default.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://hanlovesong.gitee.io/2021/02/25/GLSL%E8%AF%AD%E6%B3%95/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css"><script>var GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  ClickShowText: undefined,
  lightbox: 'mediumZoom',
  Snackbar: undefined,
  justifiedGallery: {
    js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
    css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
  },
  isPhotoFigcaption: true,
  islazyload: false,
  isanchor: true
};

var saveToLocal = {
  set: function setWithExpiry(key, value, ttl) {
    const now = new Date()
    const expiryDay = ttl * 86400000
    const item = {
      value: value,
      expiry: now.getTime() + expiryDay,
    }
    localStorage.setItem(key, JSON.stringify(item))
  },

  get: function getWithExpiry(key) {
    const itemStr = localStorage.getItem(key)

    if (!itemStr) {
      return undefined
    }
    const item = JSON.parse(itemStr)
    const now = new Date()

    if (now.getTime() > item.expiry) {
      localStorage.removeItem(key)
      return undefined
    }
    return item.value
  }
}</script><script id="config_change">var GLOBAL_CONFIG_SITE = { 
  isPost: true,
  isHome: false,
  isHighlightShrink: undefined,
  isToc: true,
  postUpdate: '2021-02-25 21:09:01'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(function () {  window.activateDarkMode = function () {
    document.documentElement.setAttribute('data-theme', 'dark')
    if (document.querySelector('meta[name="theme-color"]') !== null) {
      document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
    }
  }
  window.activateLightMode = function () {
    document.documentElement.setAttribute('data-theme', 'light')
   if (document.querySelector('meta[name="theme-color"]') !== null) {
      document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
    }
  }
  const autoChangeMode = 'false'
  const t = saveToLocal.get('theme')
  if (autoChangeMode === '1') {
    const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
    const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
    const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches
    const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified
    if (t === undefined) {
      if (isLightMode) activateLightMode()
      else if (isDarkMode) activateDarkMode()
      else if (isNotSpecified || hasNoSupport) {
        const now = new Date()
        const hour = now.getHours()
        const isNight = hour <= 6 || hour >= 18
        isNight ? activateDarkMode() : activateLightMode()
      }
      window.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) {
        if (saveToLocal.get('theme') === undefined) {
          e.matches ? activateDarkMode() : activateLightMode()
        }
      })
    } else if (t === 'light') activateLightMode()
    else activateDarkMode()
  } else if (autoChangeMode === '2') {
    const now = new Date()
    const hour = now.getHours()
    const isNight = hour <= 6 || hour >= 18
    if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
    else if (t === 'light') activateLightMode()
    else activateDarkMode()
  } else {
    if (t === 'dark') activateDarkMode()
    else if (t === 'light') activateLightMode()
  }const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
   if (asideStatus === 'hide') {
     document.documentElement.classList.add('hide-aside')
   } else {
     document.documentElement.classList.remove('hide-aside')
   }
}})()</script><meta name="generator" content="Hexo 5.2.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2323788726,242559414&amp;fm=26&amp;gp=0.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">51</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">18</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">18</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 收藏</span></a></div></div></div></div><div id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url(https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/img/default.jpg)"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Lo动乾坤</a></span><span id="menus"><div id="search_button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 收藏</span></a></div></div><span class="close" id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></span></span></nav><div id="post-info"><h1 class="post-title">GLSL语法</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-02-25T12:02:34.000Z" title="发表于 2021-02-25 20:02:34">2021-02-25</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2021-02-25T13:09:01.190Z" title="更新于 2021-02-25 21:09:01">2021-02-25</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E7%BC%96%E7%A8%8B/">编程</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E7%BC%96%E7%A8%8B/OpenGL/">OpenGL</a></span></div><div class="meta-secondline"> <span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">6.2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>24分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="glsl-中文手册"><a class="markdownIt-Anchor" href="#glsl-中文手册"></a> GLSL 中文手册</h1>
<h3 id="基本类型"><a class="markdownIt-Anchor" href="#基本类型"></a> 基本类型:</h3>
<table>
<thead>
<tr>
<th>类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>void</strong></td>
<td>空类型,即不返回任何值</td>
</tr>
<tr>
<td><strong>bool</strong></td>
<td>布尔类型 true,false</td>
</tr>
<tr>
<td><strong>int</strong></td>
<td>带符号的整数 signed integer</td>
</tr>
<tr>
<td><strong>float</strong></td>
<td>带符号的浮点数 floating scalar</td>
</tr>
<tr>
<td><strong>vec2, vec3, vec4</strong></td>
<td>n维浮点数向量 n-component floating point vector</td>
</tr>
<tr>
<td><strong>bvec2, bvec3, bvec4</strong></td>
<td>n维布尔向量 Boolean vector</td>
</tr>
<tr>
<td><strong>ivec2, ivec3, ivec4</strong></td>
<td>n维整数向量 signed integer vector</td>
</tr>
<tr>
<td><strong>mat2, mat3, mat4</strong></td>
<td>2x2, 3x3, 4x4 浮点数矩阵 float matrix</td>
</tr>
<tr>
<td><strong>sampler2D</strong></td>
<td>2D纹理 a 2D texture</td>
</tr>
<tr>
<td><strong>samplerCube</strong></td>
<td>盒纹理 cube mapped texture</td>
</tr>
</tbody>
</table>
<h3 id="基本结构和数组"><a class="markdownIt-Anchor" href="#基本结构和数组"></a> 基本结构和数组:</h3>
<table>
<thead>
<tr>
<th>类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>结构</td>
<td>struct type-name{} 类似c语言中的 结构体</td>
</tr>
<tr>
<td>数组</td>
<td>float foo[3] glsl只支持1维数组,数组可以是结构体的成员</td>
</tr>
</tbody>
</table>
<h3 id="向量的分量访问"><a class="markdownIt-Anchor" href="#向量的分量访问"></a> 向量的分量访问:</h3>
<p>glsl中的向量(vec2,vec3,vec4)往往有特殊的含义,比如可能代表了一个空间坐标(x,y,z,w),或者代表了一个颜色(r,g,b,a),再或者代表一个纹理坐标(s,t,p,q)<br />
所以glsl提供了一些更人性化的分量访问方式.</p>
<p><code>vector.xyzw</code>  其中xyzw 可以任意组合</p>
<p><code>vector.rgba</code>  其中rgba 可以任意组合</p>
<p><code>vector.stpq</code>  其中rgba 可以任意组合</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec4</span> v=<span class="type">vec4</span>(<span class="number">1.0</span>,<span class="number">2.0</span>,<span class="number">3.0</span>,<span class="number">1.0</span>);</span><br><span class="line"><span class="type">float</span> x = v.x; <span class="comment">//1.0</span></span><br><span class="line"><span class="type">float</span> x1 = v.r; <span class="comment">//1.0</span></span><br><span class="line"><span class="type">float</span> x2 = v[<span class="number">0</span>]; <span class="comment">//1.0</span></span><br><span class="line"></span><br><span class="line"><span class="type">vec3</span> xyz = v.xyz; <span class="comment">//vec3(1.0,2.0,3.0)</span></span><br><span class="line"><span class="type">vec3</span> xyz1 = vec(v[<span class="number">0</span>],v[<span class="number">1</span>],v[<span class="number">2</span>]); <span class="comment">//vec3(1.0,2.0,3.0)</span></span><br><span class="line"><span class="type">vec3</span> rgb = v.rgb; <span class="comment">//vec3(1.0,2.0,3.0)</span></span><br><span class="line"></span><br><span class="line"><span class="type">vec2</span> xyzw = v.xyzw; <span class="comment">//vec4(1.0,2.0,3.0,1.0);</span></span><br><span class="line"><span class="type">vec2</span> rgba = v.rgba; <span class="comment">//vec4(1.0,2.0,3.0,1.0);</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="运算符"><a class="markdownIt-Anchor" href="#运算符"></a> 运算符:</h3>
<table>
<thead>
<tr>
<th>优先级(越小越高)</th>
<th>运算符</th>
<th>说明</th>
<th>结合性</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><strong>()</strong></td>
<td>聚组:a*(b+c)</td>
<td>N/A</td>
</tr>
<tr>
<td>2</td>
<td><strong>[] () . ++ –</strong></td>
<td>数组下标__[]<strong>,方法参数__fun(arg1,arg2,arg3)</strong>,属性访问__a.b__,自增/减后缀__a++  a–__</td>
<td>L - R</td>
</tr>
<tr>
<td>3</td>
<td><strong>++ – + - !</strong></td>
<td>自增/减前缀__++a  --a__,正负号(一般正号不写)<strong>a ,-a</strong>,取反__!false__</td>
<td>R - L</td>
</tr>
<tr>
<td>4</td>
<td><strong>* /</strong></td>
<td>乘除数学运算</td>
<td>L - R</td>
</tr>
<tr>
<td>5</td>
<td><strong>+ -</strong></td>
<td>加减数学运算</td>
<td>L - R</td>
</tr>
<tr>
<td>7</td>
<td><strong>&lt; &gt; &lt;= &gt;=</strong></td>
<td>关系运算符</td>
<td>L - R</td>
</tr>
<tr>
<td>8</td>
<td><strong>== !=</strong></td>
<td>相等性运算符</td>
<td>L - R</td>
</tr>
<tr>
<td>12</td>
<td><strong>&amp;&amp;</strong></td>
<td>逻辑与</td>
<td>L - R</td>
</tr>
<tr>
<td>13</td>
<td><strong>^^</strong></td>
<td>逻辑排他或(用处基本等于!=)</td>
<td>L - R</td>
</tr>
<tr>
<td>14</td>
<td><strong>||</strong></td>
<td>逻辑或</td>
<td>L - R</td>
</tr>
<tr>
<td>15</td>
<td><strong>? :</strong></td>
<td>三目运算符</td>
<td>L - R</td>
</tr>
<tr>
<td>16</td>
<td><strong>= += -= *= /=</strong></td>
<td>赋值与复合赋值</td>
<td>L - R</td>
</tr>
<tr>
<td>17</td>
<td><strong>,</strong></td>
<td>顺序分配运算</td>
<td>L - R</td>
</tr>
</tbody>
</table>
<p><em>ps 左值与右值:</em></p>
<pre><code>左值:表示一个储存位置,可以是变量,也可以是表达式,但表达式最后的结果必须是一个储存位置.

右值:表示一个值, 可以是一个变量或者表达式再或者纯粹的值.

操作符的优先级：决定含有多个操作符的表达式的求值顺序，每个操作的优先级不同.

操作符的结合性：决定相同优先级的操作符是从左到右计算，还是从右到左计算。
</code></pre>
<h3 id="基础类型间的运算"><a class="markdownIt-Anchor" href="#基础类型间的运算"></a> 基础类型间的运算:</h3>
<p>glsl中,没有隐式类型转换,原则上glsl要求任何表达式左右两侧(l-value),(r-value)的类型必须一致 也就是说以下表达式都是错误的:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a =<span class="number">2.0</span>; <span class="comment">//错误,r-value为float 而 lvalue 为int.</span></span><br><span class="line"><span class="type">int</span> a =<span class="number">1.0</span>+<span class="number">2</span>;</span><br><span class="line"><span class="type">float</span> a =<span class="number">2</span>;</span><br><span class="line"><span class="type">float</span> a =<span class="number">2.0</span>+<span class="number">1</span>;</span><br><span class="line"><span class="type">bool</span> a = <span class="number">0</span>; </span><br><span class="line"><span class="type">vec3</span> a = <span class="type">vec3</span>(<span class="number">1.0</span>, <span class="number">2.0</span>, <span class="number">3.0</span>) * <span class="number">2</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>下面来分别说说可能遇到的情况:</strong></p>
<p><strong>1.<code>float</code> 与 <code>int</code>:</strong></p>
<p>float与float , int与int之间是可以直接运算的,但float与int不行.它们需要进行一次显示转换.即要么把float转成int: <strong>int(1.0)</strong><br />
,要么把int转成float: <strong>float(1)</strong> ,以下表达式都是正确的:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a=<span class="type">int</span>(<span class="number">2.0</span>);</span><br><span class="line"><span class="type">float</span> a= <span class="type">float</span>(<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> a=<span class="type">int</span>(<span class="number">2.0</span>)*<span class="number">2</span> + <span class="number">1</span>;</span><br><span class="line"><span class="type">float</span> a= <span class="type">float</span>(<span class="number">2</span>)*<span class="number">6.0</span>+<span class="number">2.3</span>;</span><br></pre></td></tr></table></figure>
<p><strong>2.<code>float</code>  与 <code>vec(向量)</code> <code>mat(矩阵)</code>:</strong></p>
<p>vec,mat这些类型其实是由float复合而成的,当它们与float运算时,其实就是在每一个分量上分别与float进行运算,这就是所谓的<code>逐分量</code>运算.glsl里<br />
大部分涉及vec,mat的运算都是<code>逐分量</code>运算,但也并不全是. 下文中就会讲到特例.</p>
<p><code>逐分量</code>运算是线性的,这就是说 vec 与 float 的运算结果是还是 vec.</p>
<p>int 与 vec,mat之间是不可运算的, 因为vec和mat中的每一个分量都是 float 类型的. 无法与int进行逐分量计算.</p>
<p>下面枚举了几种 float 与 vec,mat 运算的情况</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec3</span> a = <span class="type">vec3</span>(<span class="number">1.0</span>, <span class="number">2.0</span>, <span class="number">3.0</span>);</span><br><span class="line"><span class="type">mat3</span> m = <span class="type">mat3</span>(<span class="number">1.0</span>);</span><br><span class="line"><span class="type">float</span> s = <span class="number">10.0</span>;</span><br><span class="line"><span class="type">vec3</span> b = s * a; <span class="comment">// vec3(10.0, 20.0, 30.0)</span></span><br><span class="line"><span class="type">vec3</span> c = a * s; <span class="comment">// vec3(10.0, 20.0, 30.0)</span></span><br><span class="line"><span class="type">mat3</span> m2 = s * m; <span class="comment">// = mat3(10.0)</span></span><br><span class="line"><span class="type">mat3</span> m3 = m * s; <span class="comment">// = mat3(10.0)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>3. <code>vec(向量)</code> 与 <code>vec(向量)</code>:</strong></p>
<p>两向量间的运算首先要保证操作数的阶数都相同.否则不能计算.例如: vec3*vec2 vec4+vec3 等等都是不行的.</p>
<p>它们的计算方式是两操作数在同位置上的分量分别进行运算,其本质还是逐分量进行的,这和上面所说的float类型的<br />
逐分量运算可能有一点点差异,相同的是 vec 与 vec 运算结果还是 vec, 且阶数不变.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec3</span> a = <span class="type">vec3</span>(<span class="number">1.0</span>, <span class="number">2.0</span>, <span class="number">3.0</span>);</span><br><span class="line"><span class="type">vec3</span> b = <span class="type">vec3</span>(<span class="number">0.1</span>, <span class="number">0.2</span>, <span class="number">0.3</span>);</span><br><span class="line"><span class="type">vec3</span> c = a + b; <span class="comment">// = vec3(1.1, 2.2, 3.3)</span></span><br><span class="line"><span class="type">vec3</span> d = a * b; <span class="comment">// = vec3(0.1, 0.4, 0.9)</span></span><br></pre></td></tr></table></figure>
<p><img src="http://wshxbqq-wshxbqq.stor.sinaapp.com/2016-08-08_16-15-35_329___2.png" alt="" /></p>
<p><strong>3. <code>vec(向量)</code> 与 <code>mat(矩阵)</code>:</strong></p>
<p>要保证操作数的阶数相同,且vec与mat间只存在乘法运算.</p>
<p>它们的计算方式和线性代数中的矩阵乘法相同,不是逐分量运算.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec2</span> v = <span class="type">vec2</span>(<span class="number">10.</span>, <span class="number">20.</span>);</span><br><span class="line"><span class="type">mat2</span> m = <span class="type">mat2</span>(<span class="number">1.</span>, <span class="number">2.</span>,  <span class="number">3.</span>, <span class="number">4.</span>);</span><br><span class="line"><span class="type">vec2</span> w = m * v; <span class="comment">// = vec2(1. * 10. + 3. * 20., 2. * 10. + 4. * 20.)</span></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="type">vec2</span> v = <span class="type">vec2</span>(<span class="number">10.</span>, <span class="number">20.</span>);</span><br><span class="line"><span class="type">mat2</span> m = <span class="type">mat2</span>(<span class="number">1.</span>, <span class="number">2.</span>,  <span class="number">3.</span>, <span class="number">4.</span>);</span><br><span class="line"><span class="type">vec2</span> w = v * m; <span class="comment">// = vec2(1. * 10. + 2. * 20., 3. * 10. + 4. * 20.)</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>向量与矩阵的乘法规则如下:</p>
<p><img src="http://wshxbqq-wshxbqq.stor.sinaapp.com/2016-08-08_16-15-36_966___3.png" alt="" /></p>
<p><img src="http://wshxbqq-wshxbqq.stor.sinaapp.com/2016-08-08_16-15-36_284___4.png" alt="" /></p>
<p><strong>4. <code>mat(矩阵)</code> 与 <code>mat(矩阵)</code>:</strong></p>
<p>要保证操作数的阶数相同.</p>
<p>在mat与mat的运算中, 除了乘法是线性代数中的矩阵乘法外.其余的运算任为逐分量运算.简单说就是只有乘法是特殊的,其余都和vec与vec运算类似.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">mat2</span> a = <span class="type">mat2</span>(<span class="number">1.</span>, <span class="number">2.</span>,  <span class="number">3.</span>, <span class="number">4.</span>);</span><br><span class="line"><span class="type">mat2</span> b = <span class="type">mat2</span>(<span class="number">10.</span>, <span class="number">20.</span>,  <span class="number">30.</span>, <span class="number">40.</span>);</span><br><span class="line"><span class="type">mat2</span> c = a * b; <span class="comment">//mat2(1.*10.+3.*20.,2.*10.+4.*20.,1.* 30.+3.*40.,2.* 30.+4.*40.);</span></span><br><span class="line"></span><br><span class="line"><span class="type">mat2</span> d = a+b;<span class="comment">//mat2(1.+10.,2.+20.,3.+30.,4.+40);</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>矩阵乘法规则如下:</p>
<p><img src="http://wshxbqq-wshxbqq.stor.sinaapp.com/2016-08-08_16-15-36_985___5.png" alt="" /></p>
<h3 id="变量限定符"><a class="markdownIt-Anchor" href="#变量限定符"></a> 变量限定符:</h3>
<table>
<thead>
<tr>
<th>修饰符</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>none</strong></td>
<td>(默认的可省略)本地变量,可读可写,函数的输入参数既是这种类型</td>
</tr>
<tr>
<td><strong>const</strong></td>
<td>声明变量或函数的参数为只读类型</td>
</tr>
<tr>
<td><strong>attribute</strong></td>
<td>只能存在于vertex shader中,一般用于保存顶点或法线数据,它可以在数据缓冲区中读取数据</td>
</tr>
<tr>
<td><strong>uniform</strong></td>
<td>在运行时shader无法改变uniform变量, 一般用来放置程序传递给shader的变换矩阵，材质，光照参数等等.</td>
</tr>
<tr>
<td><strong>varying</strong></td>
<td>主要负责在vertex 和 fragment 之间传递变量</td>
</tr>
</tbody>
</table>
<p><strong>const</strong>:</p>
<p>和C语言类似,被const限定符修饰的变量初始化后不可变,除了局部变量,函数参数也可以使用const修饰符.但要注意的是结构变量可以用const修饰,<br />
但结构中的字段不行.</p>
<p>const变量必须在声明时就初始化 <code>const vec3 v3 = vec3(0.,0.,0.)</code></p>
<p>局部变量只能使用const限定符.</p>
<p>函数参数只能使用const限定符.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">struct light &#123;</span><br><span class="line">        <span class="type">vec4</span> color;</span><br><span class="line">        <span class="type">vec3</span> pos;</span><br><span class="line">        <span class="comment">//const vec3 pos1; //结构中的字段不可用const修饰会报错.</span></span><br><span class="line">    &#125;;</span><br><span class="line"><span class="keyword">const</span> light lgt = light(<span class="type">vec4</span>(<span class="number">1.0</span>), <span class="type">vec3</span>(<span class="number">0.0</span>)); <span class="comment">//结构变量可以用const修饰</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>attribute</strong>:</p>
<p>attribute变量是<code>全局</code>且<code>只读</code>的,它只能在vertex shader中使用,只能与浮点数,向量或矩阵变量组合,<br />
一般attribute变量用来放置程序传递来的模型顶点,法线,颜色,纹理等数据它可以访问数据缓冲区<br />
(还记得__gl.vertexAttribPointer__这个函数吧)</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">attribute</span> <span class="type">vec4</span> a_Position;</span><br></pre></td></tr></table></figure>
<p><strong>uniform</strong>:</p>
<p>uniform变量是<code>全局</code>且<code>只读</code>的,在整个shader执行完毕前其值不会改变,他可以和任意基本类型变量组合,<br />
一般我们使用uniform变量来放置外部程序传递来的环境数据(如点光源位置,模型的变换矩阵等等)<br />
这些数据在运行中显然是不需要被改变的.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">uniform</span> <span class="type">vec4</span> lightPosition;</span><br></pre></td></tr></table></figure>
<p><strong>varying</strong>:</p>
<p>varying类型变量是 vertex shader 与 fragment shader 之间的信使,一般我们在 vertex shader 中修改它然后在fragment shader使用它,但不能在<br />
fragment shader中修改它.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//顶点着色器</span></span><br><span class="line"><span class="keyword">varying</span> <span class="type">vec4</span> v_Color;</span><br><span class="line"><span class="type">void</span> main()&#123; </span><br><span class="line">    ...</span><br><span class="line">    v_Color = <span class="type">vec4</span>(<span class="number">1.</span>,<span class="number">1.</span>,<span class="number">1.</span>,<span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//片元着色器</span></span><br><span class="line">...</span><br><span class="line"><span class="keyword">varying</span> <span class="type">vec4</span> v_Color;</span><br><span class="line"><span class="type">void</span> main() &#123;</span><br><span class="line">  <span class="built_in">gl_FragColor</span> = v_Color;</span><br><span class="line">&#125;</span><br><span class="line">...</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>要注意全局变量限制符只能为 const、attribute、uniform和varying中的一个.不可复合.</p>
<h3 id="函数参数限定符"><a class="markdownIt-Anchor" href="#函数参数限定符"></a> 函数参数限定符:</h3>
<p>函数的参数默认是以拷贝的形式传递的,也就是值传递,任何传递给函数参数的变量,其值都会被复制一份,然后再交给函数内部进行处理.<br />
我们可以为参数添加限定符来达到传递引用的目的,glsl中提供的参数限定符如下:</p>
<table>
<thead>
<tr>
<th>限定符</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>&lt; none: default &gt;</td>
<td>默认使用 in 限定符</td>
</tr>
<tr>
<td>in</td>
<td>复制到函数中在函数中可读写</td>
</tr>
<tr>
<td>out</td>
<td>返回时从函数中复制出来</td>
</tr>
<tr>
<td>inout</td>
<td>复制到函数中并在返回时复制出来</td>
</tr>
</tbody>
</table>
<p><code>in</code> 是函数参数的默认限定符,最终真正传入函数形参的其实是实参的一份拷贝.在函数中,修改in修饰的形参不会影响到实参变量本身.</p>
<p><code>out</code> 它的作用是向函数外部传递新值,out模式下传递进来的参数是write-only的(可写不可读).就像是一个&quot;坑位&quot;,坑位中的值需要函数给他赋予.<br />
在函数中,修改out修饰的形参会影响到实参本身.</p>
<p><code>inout</code> inout下,形参可以被理解为是一个带值的&quot;坑位&quot;,及可读也可写,在函数中,修改inout修饰的形参会影响到实参本身.</p>
<h3 id="glsl的函数"><a class="markdownIt-Anchor" href="#glsl的函数"></a> glsl的函数:</h3>
<p>glsl允许在程序的最外部声明函数.函数不能嵌套,不能递归调用,且必须声明返回值类型(无返回值时声明为void) 在其他方面glsl函数与c函数非常类似.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec4</span> getPosition()&#123; </span><br><span class="line">    <span class="type">vec4</span> v4 = <span class="type">vec4</span>(<span class="number">0.</span>,<span class="number">0.</span>,<span class="number">0.</span>,<span class="number">1.</span>);</span><br><span class="line">    <span class="keyword">return</span> v4;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> doubleSize(<span class="keyword">inout</span> <span class="type">float</span> size)&#123;</span><br><span class="line">    size= size*<span class="number">2.0</span>  ;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">void</span> main() &#123;</span><br><span class="line">    <span class="type">float</span> psize= <span class="number">10.0</span>;</span><br><span class="line">    doubleSize(psize);</span><br><span class="line">    <span class="built_in">gl_Position</span> = getPosition();</span><br><span class="line">    <span class="built_in">gl_PointSize</span> = psize;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="构造函数"><a class="markdownIt-Anchor" href="#构造函数"></a> 构造函数:</h3>
<p>glsl中变量可以在声明的时候初始化,<code>float pSize = 10.0</code> 也可以先声明然后等需要的时候在进行赋值.</p>
<p>聚合类型对象如(向量,矩阵,数组,结构) 需要使用其构造函数来进行初始化. <code>vec4 color = vec4(0.0, 1.0, 0.0, 1.0);</code></p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//一般类型</span></span><br><span class="line"><span class="type">float</span> pSize = <span class="number">10.0</span>;</span><br><span class="line"><span class="type">float</span> pSize1;</span><br><span class="line">pSize1=<span class="number">10.0</span>;</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="comment">//复合类型</span></span><br><span class="line"><span class="type">vec4</span> color = <span class="type">vec4</span>(<span class="number">0.0</span>, <span class="number">1.0</span>, <span class="number">0.0</span>, <span class="number">1.0</span>);</span><br><span class="line"><span class="type">vec4</span> color1;</span><br><span class="line">color1 =<span class="type">vec4</span>(<span class="number">0.0</span>, <span class="number">1.0</span>, <span class="number">0.0</span>, <span class="number">1.0</span>);</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="comment">//结构</span></span><br><span class="line">struct light &#123;</span><br><span class="line">    <span class="type">float</span> intensity;</span><br><span class="line">    <span class="type">vec3</span> position;</span><br><span class="line">&#125;;</span><br><span class="line">light lightVar = light(<span class="number">3.0</span>, <span class="type">vec3</span>(<span class="number">1.0</span>, <span class="number">2.0</span>, <span class="number">3.0</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">//数组</span></span><br><span class="line"><span class="keyword">const</span> <span class="type">float</span> c[<span class="number">3</span>] = <span class="type">float</span>[<span class="number">3</span>](<span class="number">5.0</span>, <span class="number">7.2</span>, <span class="number">1.1</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="类型转换"><a class="markdownIt-Anchor" href="#类型转换"></a> 类型转换:</h3>
<p>glsl可以使用构造函数进行显式类型转换,各值如下:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">bool</span> t= <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">bool</span> f = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> a = <span class="keyword">int</span>(t); <span class="comment">//true转换为1或1.0</span></span><br><span class="line"><span class="keyword">int</span> a1 = <span class="keyword">int</span>(f);<span class="comment">//false转换为0或0.0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">float</span> b = <span class="keyword">float</span>(t);</span><br><span class="line"><span class="keyword">float</span> b1 = <span class="keyword">float</span>(f);</span><br><span class="line"></span><br><span class="line"><span class="keyword">bool</span> c = <span class="keyword">bool</span>(<span class="number">0</span>);<span class="comment">//0或0.0转换为false</span></span><br><span class="line"><span class="keyword">bool</span> c1 = <span class="keyword">bool</span>(<span class="number">1</span>);<span class="comment">//非0转换为true</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">bool</span> d = <span class="keyword">bool</span>(<span class="number">0.0</span>);</span><br><span class="line"><span class="keyword">bool</span> d1 = <span class="keyword">bool</span>(<span class="number">1.0</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="精度限定"><a class="markdownIt-Anchor" href="#精度限定"></a> 精度限定:</h3>
<p>glsl在进行光栅化着色的时候,会产生大量的浮点数运算,这些运算可能是当前设备所不能承受的,所以glsl提供了3种浮点数精度,我们可以根据不同的设备来使用合适的精度.</p>
<p>在变量前面加上 <code>highp</code> <code>mediump</code> <code>lowp</code> 即可完成对该变量的精度声明.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">lowp</span> <span class="type">float</span> color;</span><br><span class="line"><span class="keyword">varying</span> <span class="keyword">mediump</span> <span class="type">vec2</span> Coord;</span><br><span class="line"><span class="keyword">lowp</span> <span class="type">ivec2</span> foo(<span class="keyword">lowp</span> <span class="type">mat3</span>);</span><br><span class="line"><span class="keyword">highp</span> <span class="type">mat4</span> m;</span><br></pre></td></tr></table></figure>
<p>我们一般在片元着色器(fragment shader)最开始的地方加上 <code>precision mediump float;</code> 便设定了默认的精度.这样所有没有显式表明精度的变量<br />
都会按照设定好的默认精度来处理.</p>
<p><strong>如何确定精度:</strong></p>
<p>变量的精度首先是由精度限定符决定的,如果没有精度限定符,则要寻找其右侧表达式中,已经确定精度的变量,一旦找到,那么整个表达式都将在该精度下运行.如果找到多个,<br />
则选择精度较高的那种,如果一个都找不到,则使用默认或更大的精度类型.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">uniform</span> <span class="keyword">highp</span> <span class="type">float</span> h1;</span><br><span class="line"><span class="keyword">highp</span> <span class="type">float</span> h2 = <span class="number">2.3</span> * <span class="number">4.7</span>; <span class="comment">//运算过程和结果都 是高精度</span></span><br><span class="line"><span class="keyword">mediump</span> <span class="type">float</span> m;</span><br><span class="line">m = <span class="number">3.7</span> * h1 * h2; <span class="comment">//运算过程 是高精度</span></span><br><span class="line">h2 = m * h1; <span class="comment">//运算过程 是高精度</span></span><br><span class="line">m = h2 – h1; <span class="comment">//运算过程 是高精度</span></span><br><span class="line">h2 = m + m; <span class="comment">//运算过程和结果都 是中等精度</span></span><br><span class="line"><span class="type">void</span> f(<span class="keyword">highp</span> <span class="type">float</span> p); <span class="comment">// 形参 p 是高精度</span></span><br><span class="line">f(<span class="number">3.3</span>); <span class="comment">//传入的 3.3是高精度</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>invariant关键字:</strong></p>
<p>由于shader在编译时会进行一些内部优化,可能会导致同样的运算在不同shader里结果不一定精确相等.这会引起一些问题,尤其是vertx shader向fragmeng shader传值的时候.<br />
所以我们需要使用<code>invariant</code> 关键字来显式要求计算结果必须精确一致. 当然我们也可使用 <code>#pragma STDGL invariant(all)</code>来命令所有输出变量必须精确一致,<br />
但这样会限制编译器优化程度,降低性能.</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#pragma STDGL invariant(all) //所有输出变量为 invariant</span></span><br><span class="line"><span class="keyword">invariant</span> <span class="keyword">varying</span> texCoord; <span class="comment">//varying在传递数据的时候声明为invariant</span></span><br></pre></td></tr></table></figure>
<p><strong>限定符的顺序:</strong></p>
<p>当需要用到多个限定符的时候要遵循以下顺序:</p>
<p>1.在一般变量中: invariant &gt; storage &gt; precision</p>
<p>2.在参数中: storage &gt; parameter &gt; precision</p>
<p>我们来举例说明:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">invariant</span> <span class="keyword">varying</span> <span class="keyword">lowp</span> <span class="type">float</span> color; <span class="comment">// invariant &gt; storage &gt; precision</span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> doubleSize(<span class="keyword">const</span> <span class="keyword">in</span> <span class="keyword">lowp</span> <span class="type">float</span> s)&#123; <span class="comment">//storage &gt; parameter &gt; precision</span></span><br><span class="line">    <span class="type">float</span> s1=s;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="预编译指令"><a class="markdownIt-Anchor" href="#预编译指令"></a> 预编译指令:</h3>
<p>以 # 开头的是预编译指令,常用的有:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> #<span class="meta-keyword">undef</span> #<span class="meta-keyword">if</span> #<span class="meta-keyword">ifdef</span> #<span class="meta-keyword">ifndef</span> #<span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">elif</span> #<span class="meta-keyword">endif</span> #<span class="meta-keyword">error</span> #<span class="meta-keyword">pragma</span> #extension #version #<span class="meta-keyword">line</span></span></span><br></pre></td></tr></table></figure>
<p>比如 <strong>#version 100</strong> 他的意思是规定当前shader使用 GLSL ES 1.00标准进行编译,如果使用这条预编译指令,则他必须出现在程序的最开始位置.</p>
<p><strong>内置的宏:</strong></p>
<p><code>__LINE__</code> : 当前源码中的行号.</p>
<p><code>__VERSION__</code> : 一个整数,指示当前的glsl版本 比如 100  ps: 100 = v1.00</p>
<p><code>GL_ES</code> : 如果当前是在 OPGL ES 环境中运行则 GL_ES 被设置成1,一般用来检查当前环境是不是 OPENGL ES.</p>
<p><code>GL_FRAGMENT_PRECISION_HIGH</code> : 如果当前系统glsl的片元着色器支持高浮点精度,则设置为1.一般用于检查着色器精度.</p>
<p>实例:</p>
<p>1.如何通过判断系统环境,来选择合适的精度:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#ifdef GL_ES //</span></span><br><span class="line"><span class="meta">#ifdef GL_FRAGMENT_PRECISION_HIGH</span></span><br><span class="line"><span class="keyword">precision</span> <span class="keyword">highp</span> <span class="type">float</span>;</span><br><span class="line"><span class="meta">#else</span></span><br><span class="line"><span class="keyword">precision</span> <span class="keyword">mediump</span> <span class="type">float</span>;</span><br><span class="line"><span class="meta">#endif</span></span><br><span class="line"><span class="meta">#endif</span></span><br></pre></td></tr></table></figure>
<p>2.自定义宏:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#define NUM 100</span></span><br><span class="line"><span class="meta">#if NUM==100</span></span><br><span class="line"><span class="meta">#endif</span></span><br></pre></td></tr></table></figure>
<h3 id="内置的特殊变量"><a class="markdownIt-Anchor" href="#内置的特殊变量"></a> 内置的特殊变量</h3>
<p>glsl程序使用一些特殊的内置变量与硬件进行沟通.他们大致分成两种 一种是 <code>input</code>类型,他负责向硬件(渲染管线)发送数据.<br />
另一种是<code>output</code>类型,负责向程序回传数据,以便编程时需要.</p>
<p><strong>在 vertex Shader 中:</strong></p>
<p>output 类型的内置变量:</p>
<table>
<thead>
<tr>
<th>变量</th>
<th>说明</th>
<th>单位</th>
</tr>
</thead>
<tbody>
<tr>
<td>highp vec4 <code>gl_Position</code>;</td>
<td>gl_Position 放置顶点坐标信息</td>
<td>vec4</td>
</tr>
<tr>
<td>mediump float <code>gl_PointSize</code>;</td>
<td>gl_PointSize 需要绘制点的大小,(只在gl.POINTS模式下有效)</td>
<td>float</td>
</tr>
</tbody>
</table>
<p><strong>在 fragment Shader 中:</strong></p>
<p>input 类型的内置变量:</p>
<table>
<thead>
<tr>
<th>变量</th>
<th>说明</th>
<th>单位</th>
</tr>
</thead>
<tbody>
<tr>
<td>mediump vec4 <code>gl_FragCoord</code>;</td>
<td>片元在framebuffer画面的相对位置</td>
<td>vec4</td>
</tr>
<tr>
<td>bool <code>gl_FrontFacing</code>;</td>
<td>标志当前图元是不是正面图元的一部分</td>
<td>bool</td>
</tr>
<tr>
<td>mediump vec2 <code>gl_PointCoord</code>;</td>
<td>经过插值计算后的纹理坐标,点的范围是0.0到1.0</td>
<td>vec2</td>
</tr>
</tbody>
</table>
<p>output 类型的内置变量:</p>
<table>
<thead>
<tr>
<th>变量</th>
<th>说明</th>
<th>单位</th>
</tr>
</thead>
<tbody>
<tr>
<td>mediump vec4 <code>gl_FragColor</code>;</td>
<td>设置当前片点的颜色</td>
<td>vec4 RGBA color</td>
</tr>
<tr>
<td>mediump vec4 <code>gl_FragData[n]</code></td>
<td>设置当前片点的颜色,使用glDrawBuffers数据数组</td>
<td>vec4 RGBA color</td>
</tr>
</tbody>
</table>
<h3 id="内置的常量"><a class="markdownIt-Anchor" href="#内置的常量"></a> 内置的常量</h3>
<p>glsl提供了一些内置的常量,用来说明当前系统的一些特性. 有时我们需要针对这些特性,对shader程序进行优化,让程序兼容度更好.</p>
<p><strong>在 vertex Shader 中:</strong></p>
<p>1.const mediump int <code>gl_MaxVertexAttribs</code>&gt;=8</p>
<p>gl_MaxVertexAttribs 表示在vertex shader(顶点着色器)中可用的最大attributes数.这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
不过最低不能小于 8 个.</p>
<p>2.const mediump int <code>gl_MaxVertexUniformVectors</code> &gt;= 128</p>
<p>gl_MaxVertexUniformVectors 表示在vertex shader(顶点着色器)中可用的最大uniform vectors数. 这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
不过最低不能小于 128 个.</p>
<p>3.const mediump int <code>gl_MaxVaryingVectors</code> &gt;= 8</p>
<p>gl_MaxVaryingVectors 表示在vertex shader(顶点着色器)中可用的最大varying vectors数. 这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
不过最低不能小于 8 个.</p>
<p>4.const mediump int <code>gl_MaxVertexTextureImageUnits</code> &gt;= 0</p>
<p>gl_MaxVaryingVectors 表示在vertex shader(顶点着色器)中可用的最大纹理单元数(贴图). 这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
甚至可以一个都没有(无法获取顶点纹理)</p>
<p>5.const mediump int <code>gl_MaxCombinedTextureImageUnits</code> &gt;= 8</p>
<p>gl_MaxVaryingVectors 表示在 vertex Shader和fragment Shader总共最多支持多少个纹理单元. 这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
不过最低不能小于 8 个.</p>
<p><strong>在 fragment Shader 中:</strong></p>
<p>1.const mediump int <code>gl_MaxTextureImageUnits</code> &gt;= 8</p>
<p>gl_MaxVaryingVectors 表示在 fragment Shader(片元着色器)中能访问的最大纹理单元数,这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
不过最低不能小于 8 个.</p>
<p>2.const mediump int <code>gl_MaxFragmentUniformVectors</code> &gt;= 16</p>
<p>gl_MaxFragmentUniformVectors 表示在 fragment Shader(片元着色器)中可用的最大uniform vectors数,这个值的大小取决于 OpenGL ES 在某设备上的具体实现,<br />
不过最低不能小于 16 个.</p>
<p>3.const mediump int <code>gl_MaxDrawBuffers</code> = 1</p>
<p>gl_MaxDrawBuffers 表示可用的drawBuffers数,在OpenGL ES 2.0中这个值为1, 在将来的版本可能会有所变化.</p>
<p>glsl中还有一种内置的uniform状态变量, <code>gl_DepthRange</code> 它用来表明全局深度范围.</p>
<p>结构如下:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">struct gl_DepthRangeParameters &#123;</span><br><span class="line"> <span class="keyword">highp</span> <span class="type">float</span> near; <span class="comment">// n</span></span><br><span class="line"> <span class="keyword">highp</span> <span class="type">float</span> far; <span class="comment">// f</span></span><br><span class="line"> <span class="keyword">highp</span> <span class="type">float</span> diff; <span class="comment">// f - n</span></span><br><span class="line"> &#125;;</span><br><span class="line"> <span class="keyword">uniform</span> gl_DepthRangeParameters <span class="built_in">gl_DepthRange</span>;</span><br></pre></td></tr></table></figure>
<p>除了 gl_DepthRange 外的所有uniform状态常量都已在glsl 1.30 中<code>废弃</code>.</p>
<h3 id="流控制"><a class="markdownIt-Anchor" href="#流控制"></a> 流控制</h3>
<p>glsl的流控制和c语言非常相似,这里不必再做过多说明,唯一不同的是片段着色器中有一种特殊的控制流<code>discard</code>.<br />
使用discard会退出片段着色器，不执行后面的片段着色操作。片段也不会写入帧缓冲区。</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (l = <span class="number">0</span>; l &lt; numLights; l++)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!lightExists[l]);</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    color += light[l];</span><br><span class="line">&#125;</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (i &lt; num)</span><br><span class="line">&#123;</span><br><span class="line">    sum += color[i];</span><br><span class="line">    i++;</span><br><span class="line">&#125;</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">do</span>&#123;</span><br><span class="line">    color += light[lightNum];</span><br><span class="line">    lightNum--;</span><br><span class="line">&#125;<span class="keyword">while</span> (lightNum &gt; <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="literal">true</span>)</span><br><span class="line">    <span class="keyword">discard</span>;</span><br></pre></td></tr></table></figure>
<h3 id="内置函数库"><a class="markdownIt-Anchor" href="#内置函数库"></a> 内置函数库</h3>
<p>glsl提供了非常丰富的函数库,供我们使用,这些功能都是非常有用且会经常用到的. 这些函数按功能区分大改可以分成7类:</p>
<p><strong>通用函数:</strong></p>
<p>下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>T abs(T x)</td>
<td>返回x的绝对值</td>
</tr>
<tr>
<td>T sign(T x)</td>
<td>比较x与0的值,大于,等于,小于 分别返回 1.0 ,0.0,-1.0</td>
</tr>
<tr>
<td>T floor(T x)</td>
<td>返回&lt;=x的最大整数</td>
</tr>
<tr>
<td>T ceil(T x)</td>
<td>返回&gt;=等于x的最小整数</td>
</tr>
<tr>
<td>T fract(T x)</td>
<td>获取x的小数部分</td>
</tr>
<tr>
<td>T mod(T x, T y) <br/> T mod(T x, float y)</td>
<td>取x,y的余数</td>
</tr>
<tr>
<td>T min(T x, T y) <br/> T min(T x, float y)</td>
<td>取x,y的最小值</td>
</tr>
<tr>
<td>T max(T x, T y) <br/> T max(T x, float y)</td>
<td>取x,y的最大值</td>
</tr>
<tr>
<td>T clamp(T x, T minVal, T maxVal) <br/>T clamp(T x, float minVal,float maxVal)</td>
<td>min(max(x, minVal), maxVal),返回值被限定在 minVal,maxVal之间</td>
</tr>
<tr>
<td>T mix(T x, T y, T a) <br/>  T mix(T x, T y, float a)</td>
<td>取x,y的线性混合,x*(1-a)+y*a</td>
</tr>
<tr>
<td>T step(T edge, T x)  <br/> T step(float edge, T x)</td>
<td>如果 x&lt;edge 返回 0.0 否则返回1.0</td>
</tr>
<tr>
<td>T smoothstep(T edge0, T edge1, T x) <br/> T smoothstep(float edge0,float edge1, T x)</td>
<td>如果x&lt;edge0 返回 0.0 如果x&gt;edge1返回1.0, 否则返回Hermite插值</td>
</tr>
</tbody>
</table>
<p><strong>角度&amp;三角函数:</strong></p>
<p>下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>T radians(T degrees)</td>
<td>角度转弧度</td>
</tr>
<tr>
<td>T degrees(T radians)</td>
<td>弧度转角度</td>
</tr>
<tr>
<td>T sin(T angle)</td>
<td>正弦函数,角度是弧度</td>
</tr>
<tr>
<td>T cos(T angle)</td>
<td>余弦函数,角度是弧度</td>
</tr>
<tr>
<td>T tan(T angle)</td>
<td>正切函数,角度是弧度</td>
</tr>
<tr>
<td>T asin(T x)</td>
<td>反正弦函数,返回值是弧度</td>
</tr>
<tr>
<td>T acos(T x)</td>
<td>反余弦函数,返回值是弧度</td>
</tr>
<tr>
<td>T atan(T y, T x)<br/>  T atan(T y_over_x)</td>
<td>反正切函数,返回值是弧度</td>
</tr>
</tbody>
</table>
<p><strong>指数函数:</strong></p>
<p>下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>T pow(T x, T y)</td>
<td>返回x的y次幂 x<sub>y</sub></td>
</tr>
<tr>
<td>T exp(T x)</td>
<td>返回x的自然指数幂 e<sub>x</sub></td>
</tr>
<tr>
<td>T log(T x)</td>
<td>返回x的自然对数 ln</td>
</tr>
<tr>
<td>T exp2(T x)</td>
<td>返回2的x次幂 2<sub>x</sub></td>
</tr>
<tr>
<td>T log2(T x)</td>
<td>返回2为底的对数 log2</td>
</tr>
<tr>
<td>T sqrt(T x)</td>
<td>开根号 √x</td>
</tr>
<tr>
<td>T inversesqrt(T x)</td>
<td>先开根号,在取倒数,就是 1/√x</td>
</tr>
</tbody>
</table>
<p><strong>几何函数:</strong></p>
<p>下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>float length(T x)</td>
<td>返回矢量x的长度</td>
</tr>
<tr>
<td>float distance(T p0, T p1)</td>
<td>返回p0  p1两点的距离</td>
</tr>
<tr>
<td>float dot(T x, T y)</td>
<td>返回x y的点积</td>
</tr>
<tr>
<td>vec3 cross(vec3 x, vec3 y)</td>
<td>返回x y的叉积</td>
</tr>
<tr>
<td>T normalize(T x)</td>
<td>对x进行归一化,保持向量方向不变但长度变为1</td>
</tr>
<tr>
<td>T faceforward(T N, T I, T Nref)</td>
<td>根据 矢量 N 与Nref 调整法向量</td>
</tr>
<tr>
<td>T reflect(T I, T N)</td>
<td>返回 I - 2 * dot(N,I) * N, 结果是入射矢量 I 关于法向量N的 镜面反射矢量</td>
</tr>
<tr>
<td>T refract(T I, T N, float eta)</td>
<td>返回入射矢量I关于法向量N的折射矢量,折射率为eta</td>
</tr>
</tbody>
</table>
<p><strong>矩阵函数:</strong></p>
<p>mat可以为任意类型矩阵.</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>mat matrixCompMult(mat x, mat y)</td>
<td>将矩阵 x 和 y的元素逐分量相乘</td>
</tr>
</tbody>
</table>
<p><strong>向量函数:</strong></p>
<p>下文中的 类型 T可以是 vec2, vec3, vec4, 且可以逐分量操作.</p>
<p>bvec指的是由bool类型组成的一个向量:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec3</span> v3= <span class="type">vec3</span>(<span class="number">0.</span>,<span class="number">0.</span>,<span class="number">0.</span>);</span><br><span class="line"><span class="type">vec3</span> v3_1= <span class="type">vec3</span>(<span class="number">1.</span>,<span class="number">1.</span>,<span class="number">1.</span>);</span><br><span class="line"><span class="type">bvec3</span> aa= <span class="built_in">lessThan</span>(v3,v3_1); <span class="comment">//bvec3(true,true,true)</span></span><br></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>bvec lessThan(T x, T y)</td>
<td>逐分量比较x &lt; y,将结果写入bvec对应位置</td>
</tr>
<tr>
<td>bvec lessThanEqual(T x, T y)</td>
<td>逐分量比较 x &lt;= y,将结果写入bvec对应位置</td>
</tr>
<tr>
<td>bvec  greaterThan(T x, T y)</td>
<td>逐分量比较 x &gt; y,将结果写入bvec对应位置</td>
</tr>
<tr>
<td>bvec greaterThanEqual(T x, T y)</td>
<td>逐分量比较  x &gt;= y,将结果写入bvec对应位置</td>
</tr>
<tr>
<td>bvec equal(T x, T y) <br/> bvec equal(bvec x, bvec y)</td>
<td>逐分量比较 x == y,将结果写入bvec对应位置</td>
</tr>
<tr>
<td>bvec notEqual(T x, T y) <br/> bvec notEqual(bvec x, bvec y)</td>
<td>逐分量比较 x!= y,将结果写入bvec对应位置</td>
</tr>
<tr>
<td>bool any(bvec x)</td>
<td>如果x的任意一个分量是true,则结果为true</td>
</tr>
<tr>
<td>bool all(bvec x)</td>
<td>如果x的所有分量是true,则结果为true</td>
</tr>
<tr>
<td>bvec not(bvec x)</td>
<td>bool矢量的逐分量取反</td>
</tr>
</tbody>
</table>
<p><strong>纹理查询函数:</strong></p>
<p>图像纹理有两种 一种是平面2d纹理,另一种是盒纹理,针对不同的纹理类型有不同访问方法.</p>
<p>纹理查询的最终目的是从sampler中提取指定坐标的颜色信息. 函数中带有Cube字样的是指 需要传入盒状纹理. 带有Proj字样的是指带投影的版本.</p>
<p>以下函数只在vertex shader中可用:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DLod</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec2</span> coord, <span class="type">float</span> lod);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DProjLod</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec3</span> coord, <span class="type">float</span> lod);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DProjLod</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec4</span> coord, <span class="type">float</span> lod);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">textureCubeLod</span>(<span class="type">samplerCube</span> sampler, <span class="type">vec3</span> coord, <span class="type">float</span> lod);</span><br></pre></td></tr></table></figure>
<p>以下函数只在fragment shader中可用:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec4</span> <span class="built_in">texture2D</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec2</span> coord, <span class="type">float</span> bias);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DProj</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec3</span> coord, <span class="type">float</span> bias);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DProj</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec4</span> coord, <span class="type">float</span> bias);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">textureCube</span>(<span class="type">samplerCube</span> sampler, <span class="type">vec3</span> coord, <span class="type">float</span> bias);</span><br></pre></td></tr></table></figure>
<p>在 vertex shader 与 fragment shader 中都可用:</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec4</span> <span class="built_in">texture2D</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec2</span> coord);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DProj</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec3</span> coord);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">texture2DProj</span>(<span class="type">sampler2D</span> sampler, <span class="type">vec4</span> coord);</span><br><span class="line"><span class="type">vec4</span> <span class="built_in">textureCube</span>(<span class="type">samplerCube</span> sampler, <span class="type">vec3</span> coord);</span><br></pre></td></tr></table></figure>
<h3 id="官方的shader范例"><a class="markdownIt-Anchor" href="#官方的shader范例"></a> 官方的shader范例:</h3>
<p>下面的shader如果你可以一眼看懂,说明你已经对glsl语言基本掌握了.</p>
<p><strong>Vertex Shader:</strong></p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">uniform</span> <span class="type">mat4</span> mvp_matrix; <span class="comment">//透视矩阵 * 视图矩阵 * 模型变换矩阵</span></span><br><span class="line"><span class="keyword">uniform</span> <span class="type">mat3</span> normal_matrix; <span class="comment">//法线变换矩阵(用于物体变换后法线跟着变换)</span></span><br><span class="line"><span class="keyword">uniform</span> <span class="type">vec3</span> ec_light_dir; <span class="comment">//光照方向</span></span><br><span class="line"><span class="keyword">attribute</span> <span class="type">vec4</span> a_vertex; <span class="comment">// 顶点坐标</span></span><br><span class="line"><span class="keyword">attribute</span> <span class="type">vec3</span> a_normal; <span class="comment">//顶点法线</span></span><br><span class="line"><span class="keyword">attribute</span> <span class="type">vec2</span> a_texcoord; <span class="comment">//纹理坐标</span></span><br><span class="line"><span class="keyword">varying</span> <span class="type">float</span> v_diffuse; <span class="comment">//法线与入射光的夹角</span></span><br><span class="line"><span class="keyword">varying</span> <span class="type">vec2</span> v_texcoord; <span class="comment">//2d纹理坐标</span></span><br><span class="line"><span class="type">void</span> main(<span class="type">void</span>)</span><br><span class="line">&#123;</span><br><span class="line"> <span class="comment">//归一化法线</span></span><br><span class="line"> <span class="type">vec3</span> ec_normal = <span class="built_in">normalize</span>(normal_matrix * a_normal);</span><br><span class="line"> <span class="comment">//v_diffuse 是法线与光照的夹角.根据向量点乘法则,当两向量长度为1是 乘积即cosθ值</span></span><br><span class="line"> v_diffuse = <span class="built_in">max</span>(<span class="built_in">dot</span>(ec_light_dir, ec_normal), <span class="number">0.0</span>);</span><br><span class="line"> v_texcoord = a_texcoord;</span><br><span class="line"> <span class="built_in">gl_Position</span> = mvp_matrix * a_vertex;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>Fragment Shader:</strong></p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">precision</span> <span class="keyword">mediump</span> <span class="type">float</span>;</span><br><span class="line"><span class="keyword">uniform</span> <span class="type">sampler2D</span> t_reflectance;</span><br><span class="line"><span class="keyword">uniform</span> <span class="type">vec4</span> i_ambient;</span><br><span class="line"><span class="keyword">varying</span> <span class="type">float</span> v_diffuse;</span><br><span class="line"><span class="keyword">varying</span> <span class="type">vec2</span> v_texcoord;</span><br><span class="line"><span class="type">void</span> main (<span class="type">void</span>)</span><br><span class="line">&#123;</span><br><span class="line"> <span class="type">vec4</span> color = <span class="built_in">texture2D</span>(t_reflectance, v_texcoord);</span><br><span class="line"> <span class="comment">//这里分解开来是 color*vec3(1,1,1)*v_diffuse + color*i_ambient</span></span><br><span class="line"> <span class="comment">//色*光*夹角cos + 色*环境光</span></span><br><span class="line"> <span class="built_in">gl_FragColor</span> = color*(<span class="type">vec4</span>(v_diffuse) + i_ambient);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:657220266@qq.com">韩少邱</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://hanlovesong.gitee.io/2021/02/25/GLSL%E8%AF%AD%E6%B3%95/">https://hanlovesong.gitee.io/2021/02/25/GLSL%E8%AF%AD%E6%B3%95/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://hanlovesong.gitee.io" target="_blank">Lo动乾坤</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/GLSL/">GLSL</a></div><div class="post_share"></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2021/02/25/%E8%BE%90%E5%B0%84%E5%BA%A6%E9%87%8F%E5%AD%A6/"><img class="prev-cover" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/img/default.jpg" onerror="onerror=null;src='/img/404.jpg'"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">辐射度量学</div></div></a></div><div class="next-post pull-right"><a href="/2021/02/21/%E8%8E%B7%E5%8F%96Shader%E7%A8%8B%E5%BA%8F%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE/"><img class="next-cover" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/img/default.jpg" onerror="onerror=null;src='/img/404.jpg'"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">获取激活的Attribute和Uniform</div></div></a></div></nav></div><div class="aside_content" id="aside_content"><div class="card-widget card-info"><div class="card-content"><div class="card-info-avatar is-center"><img class="avatar-img" src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2323788726,242559414&amp;fm=26&amp;gp=0.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">韩少邱</div><div class="author-info__description"></div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">51</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">18</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">分类</div><div class="length-num">18</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/Freedomhan"><i class="fab fa-github"></i><span>Github</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/Freedomhan" target="_blank" title="Github"><i class="fab fa-github"></i></a></div></div></div><div class="card-widget card-announcement"><div class="card-content"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">我的博客</div></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="card-content"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#glsl-%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C"><span class="toc-number">1.</span> <span class="toc-text"> GLSL 中文手册</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B"><span class="toc-number">1.0.1.</span> <span class="toc-text"> 基本类型:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84%E5%92%8C%E6%95%B0%E7%BB%84"><span class="toc-number">1.0.2.</span> <span class="toc-text"> 基本结构和数组:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%91%E9%87%8F%E7%9A%84%E5%88%86%E9%87%8F%E8%AE%BF%E9%97%AE"><span class="toc-number">1.0.3.</span> <span class="toc-text"> 向量的分量访问:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">1.0.4.</span> <span class="toc-text"> 运算符:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B%E9%97%B4%E7%9A%84%E8%BF%90%E7%AE%97"><span class="toc-number">1.0.5.</span> <span class="toc-text"> 基础类型间的运算:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8F%98%E9%87%8F%E9%99%90%E5%AE%9A%E7%AC%A6"><span class="toc-number">1.0.6.</span> <span class="toc-text"> 变量限定符:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%E9%99%90%E5%AE%9A%E7%AC%A6"><span class="toc-number">1.0.7.</span> <span class="toc-text"> 函数参数限定符:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#glsl%E7%9A%84%E5%87%BD%E6%95%B0"><span class="toc-number">1.0.8.</span> <span class="toc-text"> glsl的函数:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0"><span class="toc-number">1.0.9.</span> <span class="toc-text"> 构造函数:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2"><span class="toc-number">1.0.10.</span> <span class="toc-text"> 类型转换:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%B2%BE%E5%BA%A6%E9%99%90%E5%AE%9A"><span class="toc-number">1.0.11.</span> <span class="toc-text"> 精度限定:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%A2%84%E7%BC%96%E8%AF%91%E6%8C%87%E4%BB%A4"><span class="toc-number">1.0.12.</span> <span class="toc-text"> 预编译指令:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%86%85%E7%BD%AE%E7%9A%84%E7%89%B9%E6%AE%8A%E5%8F%98%E9%87%8F"><span class="toc-number">1.0.13.</span> <span class="toc-text"> 内置的特殊变量</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%86%85%E7%BD%AE%E7%9A%84%E5%B8%B8%E9%87%8F"><span class="toc-number">1.0.14.</span> <span class="toc-text"> 内置的常量</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%81%E6%8E%A7%E5%88%B6"><span class="toc-number">1.0.15.</span> <span class="toc-text"> 流控制</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%86%85%E7%BD%AE%E5%87%BD%E6%95%B0%E5%BA%93"><span class="toc-number">1.0.16.</span> <span class="toc-text"> 内置函数库</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%98%E6%96%B9%E7%9A%84shader%E8%8C%83%E4%BE%8B"><span class="toc-number">1.0.17.</span> <span class="toc-text"> 官方的shader范例:</span></a></li></ol></li></ol></li></ol></div></div></div><div class="card-widget card-recent-post"><div class="card-content"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2021/03/04/FABRIK/" title="FABRIK">FABRIK</a><time datetime="2021-03-03T16:00:00.000Z" title="发表于 2021-03-04 00:00:00">2021-03-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2021/03/04/%E9%80%86%E5%90%91%E8%BF%90%E5%8A%A8%E5%AD%A6(Inverse%20Kinematics,%20IK)/" title="逆向运动学">逆向运动学</a><time datetime="2021-03-03T16:00:00.000Z" title="发表于 2021-03-04 00:00:00">2021-03-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2021/02/27/TA/" title="TA">TA</a><time datetime="2021-02-26T16:00:00.000Z" title="发表于 2021-02-27 00:00:00">2021-02-27</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2021/02/25/%E8%BE%90%E5%B0%84%E5%BA%A6%E9%87%8F%E5%AD%A6/" title="辐射度量学">辐射度量学</a><time datetime="2021-02-25T14:01:06.000Z" title="发表于 2021-02-25 22:01:06">2021-02-25</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2021/02/25/GLSL%E8%AF%AD%E6%B3%95/" title="GLSL语法">GLSL语法</a><time datetime="2021-02-25T12:02:34.000Z" title="发表于 2021-02-25 20:02:34">2021-02-25</time></div></div></div></div></div></div></div></main><footer id="footer" style="background-image: url(https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/img/default.jpg)"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2021 By 韩少邱</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div></div><hr/><div id="local-search-results"><div id="local-hits"></div><div id="local-stats"><div class="local-search-stats__hr" id="hr"><span>由</span> <a target="_blank" rel="noopener" href="https://github.com/wzpan/hexo-generator-search" style="color:#49B1F5;">hexo-generator-search</a>
 <span>提供支持</span></div></div></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js"></script><script src="/js/search/local-search.js"></script><div class="js-pjax"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css"><script src="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css"><script>$(function () {
  $('span.katex-display').wrap('<div class="katex-wrap"></div>')
})</script><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></div></body></html>